home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / rules / prs2 / prs2replace.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  8.6 KB  |  303 lines

  1. /*===================================================================
  2.  *
  3.  * FILE:
  4.  *   prs2replace.c
  5.  *
  6.  * IDENTIFICATION:
  7.  *   $Header: /private/postgres/src/rules/prs2/RCS/prs2replace.c,v 1.16 1991/11/18 22:21:22 mer Exp $
  8.  *
  9.  * DESCRIPTION:
  10.  *
  11.  *
  12.  *===================================================================
  13.  */
  14.  
  15. #include "tmp/c.h"
  16. #include "utils/log.h"
  17. #include "rules/prs2.h"
  18. #include "rules/prs2stub.h"
  19. #include "nodes/execnodes.h"    /* which includes access/rulescan.h */
  20. #include "parser/parse.h"    /* for the APPEND/DELETE */
  21.  
  22. /*-------------------------------------------------------------------
  23.  *
  24.  * prs2Replace
  25.  */
  26. Prs2Status
  27. prs2Replace(prs2EStateInfo, relationRuleInfo, explainRelation,
  28.         oldTuple, oldBuffer,
  29.         newTuple, newBuffer, rawTuple, rawBuffer,
  30.         attributeArray, numberOfAttributes, relation,
  31.         returnedTupleP, returnedBufferP)
  32. Prs2EStateInfo prs2EStateInfo;
  33. RelationRuleInfo relationRuleInfo;
  34. Relation explainRelation;
  35. HeapTuple oldTuple;
  36. Buffer oldBuffer;
  37. HeapTuple newTuple;
  38. Buffer newBuffer;
  39. HeapTuple rawTuple;
  40. Buffer rawBuffer;
  41. AttributeNumberPtr attributeArray;
  42. int numberOfAttributes;
  43. Relation relation;
  44. HeapTuple *returnedTupleP;
  45. Buffer *returnedBufferP;
  46. {
  47.     RuleLock oldLocks, oldTupleLocks, explocks;
  48.     RuleLock newLocks;
  49.     RuleLock relLocks;
  50.     RuleLock finalLocks;
  51.     Prs2Stub stubs;
  52.     Prs2OneLock oneLock;
  53.     int i,j;
  54.     AttributeValues oldAttrValues, newAttrValues, rawAttrValues;
  55.     AttributeNumber attr, maxattrs, attrno;
  56.     int newTupleMade;
  57.     Name relName;
  58.     bool insteadRuleFound;
  59.     bool insteadRuleFoundThisTime;
  60.     TupleDescriptor tupDesc;
  61.  
  62.     /*
  63.      * Find the locks of the tuple.
  64.      *
  65.      * To find the locks of the RAW(old) tuple, we have to check both
  66.      * for relation level locks and for tuple level locks.
  67.      * 
  68.      * NOTE: 'old' tuple has no lock on it, because locks
  69.      * are not propagated from node to node inside the executor.
  70.      *
  71.      * NOTE: 'on replace' rules have either a relation level
  72.      * lock, or a tuple-level-lock on the old tuple.
  73.      *
  74.      * The rule stubs need only be checked at the end, and only
  75.      * to find out what locks the "new" tuple should get.
  76.      *
  77.      */
  78.     relName = & ((RelationGetRelationTupleForm(relation))->relname);
  79.     tupDesc = RelationGetTupleDescriptor(relation);
  80.  
  81.     relLocks = relationRuleInfo->relationLocks;
  82.     stubs = relationRuleInfo->relationStubs;
  83.     if (relationRuleInfo->ignoreTupleLocks)
  84.     oldTupleLocks = prs2MakeLocks();
  85.     else
  86.     oldTupleLocks = prs2GetLocksFromTuple(rawTuple, rawBuffer);
  87.     oldLocks = prs2LockUnion(oldTupleLocks, relLocks);
  88.  
  89.     /*
  90.      * now extract from the tuple the array of the attribute values.
  91.      */
  92.     newAttrValues = attributeValuesCreate(newTuple, newBuffer, relation);
  93.     oldAttrValues = attributeValuesCreate(oldTuple, oldBuffer, relation);
  94.     rawAttrValues = attributeValuesCreate(rawTuple, rawBuffer, relation);
  95.  
  96.     /*
  97.      * First activate all the 'late evaluation' rules, i.e.
  98.      * all the rules that try to update the fields of the 'new' tuple
  99.      *
  100.      * NOTE: WE use as locks of the new tuple the locks of the old
  101.      * tuple! But in reality we are only interested in the 
  102.      * 'LockTypeReplaceWrite' locks...
  103.      */
  104.     maxattrs = RelationGetNumberOfAttributes(relation);
  105.     for(attr=1; attr <= maxattrs; attr++) {
  106.     prs2ActivateBackwardChainingRules(
  107.             prs2EStateInfo,
  108.             explainRelation,
  109.             relation,
  110.             attr,
  111.             PRS2_NEW_TUPLE,
  112.             oldTuple->t_oid,
  113.             oldAttrValues,
  114.             oldLocks,
  115.             LockTypeRetrieveWrite,
  116.             newTuple->t_oid,
  117.             newAttrValues,
  118.             oldLocks,
  119.             LockTypeReplaceWrite,
  120.             attributeArray,
  121.             numberOfAttributes);
  122.     }
  123.  
  124.     /*
  125.      * Then, activate all the 'forward chaining rules'
  126.      * NOTE: Both old & new locks have the same "LockTypeReplaceAction"
  127.      * locks
  128.      */
  129.     insteadRuleFound = false;
  130.     for(i=0; i<numberOfAttributes; i++) {
  131.     prs2ActivateForwardChainingRules(
  132.             prs2EStateInfo,
  133.             explainRelation,
  134.             relation,
  135.             attributeArray[i],
  136.             LockTypeReplaceAction,
  137.             PRS2_OLD_TUPLE,
  138.             oldTuple->t_oid,
  139.             oldAttrValues,
  140.             oldLocks,
  141.             LockTypeRetrieveWrite,
  142.             newTuple->t_oid,
  143.             newAttrValues,
  144.             InvalidRuleLock,
  145.             LockTypeInvalid,
  146.             &insteadRuleFoundThisTime,
  147.             attributeArray,
  148.             numberOfAttributes);
  149.     if (insteadRuleFoundThisTime) {
  150.         insteadRuleFound = true;
  151.     }
  152.     }
  153.     /*
  154.      * Look also for 'on replace' rules with
  155.      * an 'InvalidAttributeNumber' locked attrno.
  156.      * (I.e. rules like: 'on replace to EMP where... do...'
  157.      */
  158.     prs2ActivateForwardChainingRules(
  159.         prs2EStateInfo,
  160.         explainRelation,
  161.         relation,
  162.         InvalidAttributeNumber,
  163.         LockTypeReplaceAction,
  164.         PRS2_OLD_TUPLE,
  165.         oldTuple->t_oid,
  166.         oldAttrValues,
  167.         oldLocks,
  168.         LockTypeRetrieveWrite,
  169.         newTuple->t_oid,
  170.         newAttrValues,
  171.         InvalidRuleLock,
  172.         LockTypeInvalid,
  173.         &insteadRuleFoundThisTime,
  174.         attributeArray,
  175.         numberOfAttributes);
  176.     if (insteadRuleFoundThisTime) {
  177.     insteadRuleFound = true;
  178.     }
  179.  
  180.     /*
  181.      * Now all the correct values 
  182.      * Create a new tuple combining the 'raw' tuple, i.e. the
  183.      * tuple without any rules activated and the 'new' tuple.
  184.      */
  185.     *returnedBufferP = InvalidBuffer;
  186.     *returnedTupleP = attributeValuesCombineNewAndOldTuple(
  187.                 rawAttrValues,
  188.                 newAttrValues,
  189.                 relation,
  190.                 attributeArray,
  191.                 numberOfAttributes);
  192.  
  193.     /*
  194.      * OK, now find out the rule locks that the new tuple
  195.      * must get.
  196.      * NOTE: these locks will NOT include "export" locks
  197.      * yet. These, will be calculated in a while...
  198.      */
  199.     newLocks = prs2FindLocksForNewTupleFromStubs(
  200.             *returnedTupleP,
  201.             *returnedBufferP,
  202.             stubs,
  203.             relation);
  204.  
  205.     /*
  206.      * are there any export locks "broken" ???
  207.      * That includes
  208.      * a) new export locks that didn't exist before
  209.      * b) removal of old export locks
  210.      * c) value of an attribute locked by an export lock has changed.
  211.      */
  212.     explocks = prs2FindNewExportLocksFromLocks(newLocks);
  213.     for (i=0; i<prs2GetNumberOfLocks(explocks); i++) {
  214.     oneLock = prs2GetOneLockFromLocks(explocks, i);
  215.     if (!prs2OneLockIsMemberOfLocks(oneLock, oldLocks)) {
  216.         /*
  217.          * a brand new export lock !
  218.          */
  219.         attrno = prs2OneLockGetAttributeNumber(oneLock);
  220.         if (!newAttrValues[attrno-1].isNull)
  221.         prs2ActivateExportLockRulePlan(oneLock,
  222.                 newAttrValues[attrno-1].value,
  223.                 tupDesc->data[attrno-1]->atttypid,
  224.                 APPEND);
  225.  
  226.     }
  227.     }
  228.     for (i=0; i<prs2GetNumberOfLocks(oldLocks); i++) {
  229.     oneLock = prs2GetOneLockFromLocks(oldLocks, i);
  230.     if (prs2OneLockGetLockType(oneLock) != LockTypeExport)
  231.         continue;
  232.     if (!prs2OneLockIsMemberOfLocks(oneLock, oldLocks)) {
  233.         /*
  234.          * an old lock that has been deleted...
  235.          */
  236.         attrno = prs2OneLockGetAttributeNumber(oneLock);
  237.         if (!oldAttrValues[attrno-1].isNull)
  238.         prs2ActivateExportLockRulePlan(oneLock,
  239.                 oldAttrValues[attrno-1].value,
  240.                 tupDesc->data[attrno-1]->atttypid,
  241.                 DELETE);
  242.     }
  243.     }
  244.     for (i=0; i<prs2GetNumberOfLocks(explocks); i++) {
  245.     oneLock = prs2GetOneLockFromLocks(explocks, i);
  246.     if (prs2OneLockIsMemberOfLocks(oneLock, oldLocks)) {
  247.         /*
  248.          * this lock existed before & still exists now...
  249.          * has the locked atribute changed in any way ??
  250.          * (either by the user or by the rule ?)
  251.          */
  252.         attrno = prs2OneLockGetAttributeNumber(oneLock);
  253.         for (j=0; j<numberOfAttributes; j++) {
  254.             if (attributeArray[j] == attrno)
  255.             break;
  256.         }
  257.         if (newAttrValues[attrno-1].isChanged || j <numberOfAttributes) {
  258.         /*
  259.          * yes, this attribute values has been changed...
  260.          */
  261.         if (!oldAttrValues[attrno-1].isNull)
  262.             prs2ActivateExportLockRulePlan(oneLock,
  263.                     oldAttrValues[attrno-1].value,
  264.                     tupDesc->data[attrno-1]->atttypid,
  265.                     DELETE);
  266.         if (!newAttrValues[attrno-1].isNull)
  267.             prs2ActivateExportLockRulePlan(oneLock,
  268.                     newAttrValues[attrno-1].value,
  269.                     tupDesc->data[attrno-1]->atttypid,
  270.                     APPEND);
  271.         }
  272.     }
  273.     }
  274.         
  275.     /*
  276.      * Calculate the new locks for this tuple.
  277.      * This is the union of 'newLocks' and the 'explocks'
  278.      *
  279.      * NOTE: THING TO DO:
  280.      * REMOVE ALL IMPORT LOCKS (same thing in prs2append.c)
  281.      * THEY DON"T BREAK ANYTHING BUT THEY CHEW UP SPACE...
  282.      */
  283.     finalLocks = prs2LockUnion(newLocks, explocks);
  284.     HeapTupleSetRuleLock(*returnedTupleP, InvalidBuffer, finalLocks);
  285.     
  286.     /*
  287.      * clean up, sweep the floor and do the laundry....
  288.      */
  289.     prs2FreeLocks(oldLocks);
  290.     prs2FreeLocks(oldTupleLocks);
  291.     attributeValuesFree(newAttrValues, relation);
  292.     attributeValuesFree(oldAttrValues, relation);
  293.     prs2FreeLocks(newLocks);
  294.     prs2FreeLocks(explocks);
  295.  
  296.     if (insteadRuleFound) {
  297.     return(PRS2_STATUS_INSTEAD);
  298.     } else {
  299.     return(PRS2_STATUS_TUPLE_CHANGED);
  300.     }
  301.  
  302. }
  303.